﻿import struct
import matplotlib
from socket import *  
import numpy as np 
import scipy as sp
from scipy.fftpack import fft, ifft
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 
from matplotlib.figure import Figure
from Tkinter import *
import datetime
import time
import thread

class ZoomPan:
    def __init__(self):
        self.press = None
        self.cur_xlim = None
        self.cur_ylim = None
        self.x0 = None
        self.y0 = None
        self.x1 = None
        self.y1 = None
        self.xpress = None
        self.ypress = None
 
 
    def zoom_factory(self, ax, base_scale = 2.):
        def zoom(event):
            cur_xlim = ax.get_xlim()
            cur_ylim = ax.get_ylim()
 
            xdata = event.xdata # get event x location
            ydata = event.ydata # get event y location
 
            if event.button == 'down':
                # deal with zoom in
                scale_factor = 1 / base_scale
            elif event.button == 'up':
                # deal with zoom out
                scale_factor = base_scale
            else:
                # deal with something that should never happen
                scale_factor = 1
                print event.button
 
            new_width = (cur_xlim[1] - cur_xlim[0]) * scale_factor
            new_height = (cur_ylim[1] - cur_ylim[0]) * scale_factor
 
            relx = (cur_xlim[1] - xdata)/(cur_xlim[1] - cur_xlim[0])
            rely = (cur_ylim[1] - ydata)/(cur_ylim[1] - cur_ylim[0])
 
            ax.set_xlim([xdata - new_width * (1-relx), xdata + new_width * (relx)])
            ax.set_ylim([ydata - new_height * (1-rely), ydata + new_height * (rely)])
            ax.figure.canvas.draw()
 
        fig = ax.get_figure() # get the figure of interest
        fig.canvas.mpl_connect('scroll_event', zoom)
 
        return zoom
 
    def pan_factory(self, ax):
        def onPress(event):
            if event.inaxes != ax: return
            self.cur_xlim = ax.get_xlim()
            self.cur_ylim = ax.get_ylim()
            self.press = self.x0, self.y0, event.xdata, event.ydata
            self.x0, self.y0, self.xpress, self.ypress = self.press
 
        def onRelease(event):
            self.press = None
            ax.figure.canvas.draw()
 
        def onMotion(event):
            if self.press is None: return
            if event.inaxes != ax: return
            dx = event.xdata - self.xpress
            dy = event.ydata - self.ypress
            self.cur_xlim -= dx
            self.cur_ylim -= dy
            ax.set_xlim(self.cur_xlim)
            ax.set_ylim(self.cur_ylim)
 
            ax.figure.canvas.draw()
 
        fig = ax.get_figure() # get the figure of interest
 
        # attach the call back
        fig.canvas.mpl_connect('button_press_event',onPress)
        fig.canvas.mpl_connect('button_release_event',onRelease)
        fig.canvas.mpl_connect('motion_notify_event',onMotion)
 
        #return the function
        return onMotion

class UDPSocketClient:
    def __init__(self):
        self.mHost = '192.168.1.6'
        self.mPort = 6000 
        self.mBufsize = 4108 # 4k + 12 
        self.mAddress = (self.mHost, self.mPort)
        self.mUDPClient = socket(AF_INET, SOCK_DGRAM)
        self.mData = None
        self.mUDPClient.settimeout(5)

    def sendData(self):
        self.mUDPClient.sendto(self.mData,self.mAddress)

    def receiveData(self):
       self.mData, self.mAddress = self.mUDPClient.recvfrom(self.mBufsize)
       return self.mData
       
def bumatoyuanma(x):
   x1 = []
   x2 = []
   for i in range(len(x)):
     if (x[i] > 32768): # 除符号位外， 取反+1
        x1.append(-((x[i] ^ 65535) + 1))    
     elif (x[i] == 32768):
        x1.append(0) 
     else:
        x1.append(x[i])
        
     if (x[i] > 32767): # 除符号位外， 取反+1
        x2.append(x[i]-65536)
     else:
        x2.append(x[i])

   #print x1
   #print x2
      
   return x2
     

def bumatoyuanmaSingle(x):
  if (x > 32768): # 除符号位外， 取反+1
      x = -((x ^ 65535) + 1)    
  elif (x == 32768):
      x = 0 
  return x
     
def receiveData ():
    data, addr = udpCliSock.recvfrom(4108)
    print data
    return data 
    
def readData(datapath):
  iData = []
  for line in open(datapath):
    if len(iData) == 4096:
      break
    length = len(line)
    iData.append(int(line))
  return (iData)

def sendcommand(cmdid,status,msgid,len,type,offset):
  cmdid=struct.pack('H',htons(cmdid))
  status=struct.pack('H',status)
  msgid=struct.pack('H',htons(msgid))
  len=struct.pack('H',len)
  type=struct.pack('H',type)
  offset=struct.pack('H',offset)
  data = cmdid + status + msgid + len + type + offset
  
  #udpSocketClient = UDPSocketClient()
  udpSocketClient.mData = data
  udpSocketClient.sendData()
  
def parseData(data, withHead):
  if (withHead):
    cmdid = struct.unpack('H',data[0:2])
    print "cmd id: ", hex(ntohs(cmdid[0]))
    data = data[2:]
    status = struct.unpack('H',data[:2])
    print "status: ",hex(ntohs(status[0]))
    data = data[2:]
    msgid = struct.unpack('H',data[:2])
    print "msgid: ", hex(ntohs(msgid[0]))
    data = data[2:]
    length = struct.unpack('H',data[:2])
    print "length: ",hex(ntohs(length[0]))
    data = data[2:]
    type = struct.unpack('H',data[:2])
    print "type: ",hex(ntohs(type[0]))
    data = data[2:]
    offset = struct.unpack('H',data[:2])
    print "offset: ",hex(ntohs(offset[0]))
    
    data = data[2:]
  # Parse Payload...
  
  # Save the original payload
  now = datetime.datetime.now()
  currentTime = now.strftime('%Y-%m-%d-%H-%M-%S') 
  rawFileName = "RawIQ-" + currentTime + ".dat"
  rawFile=open(rawFileName,'wb')
  rawFile.write(data)
  rawFile.close()

  # 4096 bytes, 4 Byes I Data, 4 Bytes Q data
  iData = []
  qData= []

  for i in xrange(0,4096,8):
    iData.append(int(struct.unpack('H',data[i:i+2])[0]))
    iData.append(int(struct.unpack('H',data[i+2:i+4])[0]))
    qData.append(int(struct.unpack('H',data[i+4:i+6])[0]))
    qData.append(int(struct.unpack('H',data[i+6:i+8])[0]))
    
  iFileName = "I-" + currentTime + ".txt"
  qFileName = "Q-" + currentTime + ".txt"
  iFile=open(iFileName,'wb')
  qFile=open(qFileName,'wb')
  
  # Save the IQ Data
  for i in range(len(iData)):
     iFile.write(str(iData[i]))
     iFile.write('\n');    
     qFile.write(str(qData[i]))
     qFile.write('\n')

  iFile.close()
  qFile.close()
  
  return (iData,qData)
  
threadRunning = True

def readanddraw():
  global threadRunning
  while threadRunning:
    aiData = []
    aqData = []
    biData = []
    bqData = []
    aiData = readData("AI-2018-01-22-21-04-40.txt")
    aqData = readData("AQ-2018-01-22-21-04-40.txt")
  
    if(channelVar.get() == 1):
     drawPicture(aiData,aqData)
    else:
     drawPicture(biData,bqData)
    
    aiData = []
    aqData = []
    biData = []
    bqData = []

      
    biData = readData("BI-2018-01-22-21-04-40.txt")
    bqData = readData("BQ-2018-01-22-21-04-40.txt")
    
    # if(channelVar.get() == 1):
     # drawPicture(aiData,aqData)
    # else:
    drawPicture(biData,bqData)
  
def stopCapture():
  print "Stop Capture..."
  
  
  try:
   global threadRunning
   threadRunning = True
   thread.start_new_thread( readanddraw,() )
  except:
   print "Error: unable to start thread"
  #while True:
    # Read from File
  # aiData = []
  # aqData = []
  # biData = []
  # bqData = []
  # aiData = readData("AI-2018-01-22-21-04-40.txt")
  # aqData = readData("AQ-2018-01-22-21-04-40.txt")
  # biData = readData("BI-2018-01-22-21-04-40.txt")
  # bqData = readData("BQ-2018-01-22-21-04-40.txt")
  # #result = parseData(data, False)
  
  # if(channelVar.get() == 1):
   # drawPicture(aiData,aqData)
  # else:
   # drawPicture(biData,bqData)
  
  # aiData = []
  # aqData = []
  # biData = []
  # bqData = []
  
  # time.sleep(1)
    
    # biData = readData("BI-2018-01-22-21-04-40.txt")
    # bqData = readData("BQ-2018-01-22-21-04-40.txt")
    
    # # if(channelVar.get() == 1):
     # # drawPicture(aiData,aqData)
    # # else:
    # drawPicture(biData,bqData)

    # aiData = []
    # aqData = []
    # biData = []
    # bqData = []
    
    # time.sleep(1)
    
    
    
def drawPicture(y1, y2):
  f_plot1.clear()
  f_plot1.set_title('Signal')
  f_plot1.set_xlabel('Freqs(HZ)')
  f_plot1.set_ylabel('Value')
      
  y1 = bumatoyuanma(y1)
  y2 = bumatoyuanma(y2)
  
  
  #freqss = np.fft.fftfreq(len(y1))
  #print "freqs", freqss
  # Save to yuanma
  binfile=open("I-Yuanma.txt",'wb') 
  for i in range(len(y1)):
    binfile.write(str(y1[i]))
    binfile.write('\n')
  binfile.close()
  
  binfile=open("Q-Yuanma.txt",'wb') 
  for i in range(len(y2)):
    binfile.write(str(y2[i]))
    binfile.write('\n')
  binfile.close()
  
  y =[]
  for i in range(len(y1)):
    y.append(complex(y1[i],y2[i]))

  hanning_window = np.hanning(len(y))
  xf = np.fft.fft(y * hanning_window)
  xf = np.fft.fftshift(abs(xf))
  # for i in range(0, 10):
    # print xf[i] 
  
  # write to file
  
  # binfile=open("FFT-1.txt",'wb') 
  # binfile.write(xf)
  # # for i in range(len(xf)):
    # # binfile.write(int(xf[i]))
    # # binfile.write('\n')

  # binfile.close()
  
  sampling_rate = 1.5*1e9
  fft_size = len(y)
  #freqs = np.linspace(-491.52/2, 491.52/2, fft_size) 
  freqs = np.linspace(0, 1.5*1e9, fft_size) 
  xf = 20*np.log10(abs(xf)) 
  
  xf = (xf-xf.min())/(xf.max()-xf.min())
  
  #print xf
  #xf = 20*np.log10((xf))
  f_plot1.plot(freqs, xf)

  f.tight_layout()
  canvs.draw()


def startCapture():
  print "Start Capture..."
  global threadRunning
  threadRunning = False
  # sendcommand(0x5a04,0x0000,0xa501,0x0000,0x0000,0x0000)
  # #udpSocketClient = UDPSocketClient()
  # #binfile=open('Received-spi-updated.dat','rb')
  # #udpSocketClient.mData = binfile.read()
  
  # #parseData(udpSocketClient.mData, True)

  # udpSocketClient.receiveData()
  # # Parse Data...
  # data = udpSocketClient.mData
  # if data:
    # #binfile=open("Received-spi-updated.dat",'wb')
    # #binfile.write(data)
    # #binfile.close()
    # result = parseData(data, True)
    # iData = result[0]
    # qData = result[1]
    # drawPicture(iData,qData)
  
root = Tk()
root.wm_title('Signal Playback')

f = Figure(figsize=(5,4),dpi=100)
f_plot1 = f.add_subplot(111)
f_plot1.set_title('Signal')
f_plot1.set_xlabel('Freqs(HZ)')
f_plot1.set_ylabel('Value')

udpSocketClient = UDPSocketClient()


canvs = FigureCanvasTkAgg(f,root)
canvs.show()
canvs.get_tk_widget().pack(side=TOP ,fill=BOTH ,expand =12)


frm = Frame(root)
#Top
frm_T = Frame(frm)

Label(frm_T,text='Link Status:').pack(padx=5, pady=10, side=LEFT)
statusVal = StringVar()
statusVal.set('0')
Entry(frm_T, textvariable =statusVal,relief=SUNKEN,width=10).pack(padx=5, pady=20, side=LEFT)

channelVar = IntVar()
channelVar.set(1)
Radiobutton(frm_T, text='Channel A', variable=channelVar, value=1).pack(padx=5, pady=10, side=LEFT)
Radiobutton(frm_T, text='Channel B', variable=channelVar, value=2).pack(padx=5, pady=10, side=LEFT)
Button(frm_T, text = 'Start Capture...',command = startCapture).pack(padx=5, pady=10, side=LEFT)
Button(frm_T, text = 'Stop Capture...',command = stopCapture).pack(padx=5, pady=10, side=LEFT)
frm_T.pack(side=TOP)

frm_B = Frame(frm)
#Button(root, text = 'Show',command = drawPicture).pack(padx=5, pady=30, side=LEFT) 
Label(frm_B,text='Register Address:').pack(padx=5, pady=10, side=LEFT)
Entry(frm_B, text = "0x02", relief=SUNKEN,width=10).pack(padx=5, pady=20, side=LEFT)
Label(frm_B,text='Register Value:').pack(padx=5, pady=10, side=LEFT)
Entry(frm_B, relief=SUNKEN,width=10).pack(padx=5, pady=20, side=LEFT)
Button(frm_B, text = 'Read Register',command = drawPicture).pack(padx=5, pady=10, side=LEFT) 
Button(frm_B, text = 'Write Register',command = drawPicture).pack(padx=5, pady=10, side=LEFT) 
frm_B.pack(side= TOP)

frm.pack()

zp1 = ZoomPan()
scale = 1.1
figZoom1 = zp1.zoom_factory(f_plot1, base_scale = scale)
figPan1 = zp1.pan_factory(f_plot1)

root.mainloop()
